﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Security.Permissions;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

namespace Accumulation.Controls.Menu {
    /// <summary>
    /// 菜单
    /// </summary>
    [ParseChildren(true, "Items")
    , PersistChildren(false)
    , DefaultProperty("HTMLElementId")
    , ToolboxData("<{0}:MenuPlus runat=server></{0}:MenuPlus>")
    , AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class MenuPlus : Control, INamingContainer {
        private OverStyle _over;
        private LineStyle _line;
        private TextFontStyle _textFont;
        private IconStyle _icon;
        private ContainerStyle _container;
        private HorizontalStyle _horizontal;
        private MenuItemPluses _items;

        /// <summary>
        /// 菜单构造函数
        /// </summary>
        public MenuPlus() {
            this._over = new OverStyle() {
                BackgroundColor = ColorTranslator.FromHtml("#cccccc"),
                FontColor = ColorTranslator.FromHtml("#ff0000")
            };
            this._line = new LineStyle() { BackgroundColor = ColorTranslator.FromHtml("#000000") };
            this._textFont = new TextFontStyle() {
                Family = "Tahoma",
                Size = FontUnit.Parse("12px")
            };
            this._icon = new IconStyle() {
                BackgroundColor = ColorTranslator.FromHtml("#999999"),
                BorderRightColor = ColorTranslator.FromHtml("#cccccc")
            };
            this._container = new ContainerStyle() {
                BorderColor = ColorTranslator.FromHtml("#bbbbbb"),
                BackgroundColor = ColorTranslator.FromHtml("#fefefe"),
                BorderWidth = Unit.Parse("150px")
            };
            this._horizontal = new HorizontalStyle() {
                BorderColor = ColorTranslator.FromHtml("#bbbbbb"),
                BackgroundColor = ColorTranslator.FromHtml("#fefefe"),
                LineColor = ColorTranslator.FromHtml("#000000")
            };
        }
        /// <summary>
        /// 返回菜单 id
        /// </summary>
        [Browsable(false), Description("返回菜单 id")]
        public string MenuPlusId {
            get { return "m_" + this.ClientID; }
        }
        /// <summary>
        /// 菜单的菜单项
        /// </summary>
        [MergableProperty(false)
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , Description("菜单的菜单项")
        , PersistenceMode(PersistenceMode.InnerProperty)]
        public MenuItemPluses Items {
            get {
                if (this._items == null) {
                    this._items = new MenuItemPluses();
                }
                return this._items;
            }
        }
        /// <summary>
        /// 菜单放置的 element 的 id，右键菜单忽略，
        /// 注意元素要出现在菜单的前面，即 DOM 顺序要在菜单的前面，
        /// 未设置会自动添加
        /// </summary>
        [DefaultValue((string)null)
        , Description("菜单放置的 element 的 id，注意元素要出现在菜单的前面，即 DOM 顺序要在菜单的前面，未设置会自动添加")]
        public string HTMLElementId {
            get { return (string)ViewState["HTMLElementId"]; }
            set { ViewState["HTMLElementId"] = value; }
        }
        /// <summary>
        /// 菜单 url 打开窗口形式
        /// </summary>
        [Description("菜单 url 打开窗口形式")
        , DefaultValue(TargetEnum._BLANK)]
        public TargetEnum Target {
            get {
                object obj = ViewState["Target"];
                return object.Equals(obj, null) ? TargetEnum._BLANK : (TargetEnum)((int)obj);
            }
            set { ViewState["Target"] = value; }
        }
        /// <summary>
        /// 菜单输出的类型
        /// </summary>
        [Description("菜单输出的类型")
        , DefaultValue(OutputEnum.Vertical)]
        public OutputEnum Output {
            get {
                object obj = ViewState["Output"];
                return object.Equals(obj, null) ? OutputEnum.Vertical : (OutputEnum)((int)obj);
            }
            set { ViewState["Output"] = value; }
        }
        /// <summary>
        /// 菜单箭头 Url，为空则默认
        /// </summary>
        [Description("菜单箭头 Url，为空则默认")
        , DefaultValue((string)null)
        , Editor(typeof(ImageUrlEditor), typeof(UITypeEditor))]
        public string ArrowUrl {
            get {
                object obj = ViewState["ArrowUrl"];
                if (!object.Equals(obj, null)) { return (string)obj; }
                return string.Empty;
            }
            set { ViewState["ArrowUrl"] = value; }
        }
        /// <summary>
        /// 鼠标经过颜色样式设置
        /// </summary>
        [Description("鼠标经过颜色样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public OverStyle Over {
            get {
                object obj = ViewState["Over"];
                if (!object.Equals(obj, null)) { return (OverStyle)obj; }
                return this._over;
            }
            set { ViewState["Over"] = value; }
        }
        /// <summary>
        /// 线条颜色样式设置
        /// </summary>
        [Description("线条颜色样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public LineStyle Line {
            get {
                object obj = ViewState["Line"];
                if (!object.Equals(obj, null)) { return (LineStyle)obj; }
                return this._line;
            }
            set { ViewState["Line"] = value; }
        }
        /// <summary>
        /// 文字样式设置
        /// </summary>
        [Description("文字样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public TextFontStyle TextFont {
            get {
                object obj = ViewState["TextFont"];
                if (!object.Equals(obj, null)) { return (TextFontStyle)obj; }
                return this._textFont;
            }
            set { ViewState["TextFont"] = value; }
        }
        /// <summary>
        /// 图标样式设置
        /// </summary>
        [Description("图标样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public IconStyle Icon {
            get {
                object obj = ViewState["Icon"];
                if (!object.Equals(obj, null)) { return (IconStyle)obj; }
                return this._icon;
            }
            set { ViewState["Icon"] = value; }
        }
        /// <summary>
        /// 容器样式设置
        /// </summary>
        [Description("容器样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public ContainerStyle Container {
            get {
                object obj = ViewState["Container"];
                if (!object.Equals(obj, null)) { return (ContainerStyle)obj; }
                return this._container;
            }
            set { ViewState["Container"] = value; }
        }
        /// <summary>
        /// 水平时首行容器样式设置
        /// </summary>
        [Description("水平时首行容器样式设置")
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Content)
        , NotifyParentProperty(true)
        , PersistenceMode(PersistenceMode.InnerProperty)
        , Category("Appearance")]
        public HorizontalStyle Horizontal {
            get {
                object obj = ViewState["Horizontal"];
                if (!object.Equals(obj, null)) { return (HorizontalStyle)obj; }
                return this._horizontal;
            }
            set { ViewState["Horizontal"] = value; }
        }

        /// <summary>
        /// 重写 onprerender
        /// </summary>
        /// <param name="e">EventArgs</param>
        protected override void OnPreRender(EventArgs e) {
            HtmlLink hl = new HtmlLink();
            hl.Href = Helper.GetWebResourceUrl("Accumulation.Controls.Menu.Menu.css", this);
            hl.Attributes.Add("rel", "stylesheet");
            hl.Attributes.Add("type", "text/css");
            hl.ID = "MenuCss";
            if (!(this.Page.Header.FindControl(hl.ClientID) is HtmlLink)) {
                this.Page.Header.Controls.Add(hl);
            }

            this.Page.ClientScript.RegisterClientScriptInclude("MenuFile",
                Helper.GetWebResourceUrl("Accumulation.Controls.Menu.Menu.js", this));

            base.OnPreRender(e);
        }
        internal string Register() {
            StringBuilder sb = new StringBuilder();
            sb.Append("(function() {");
            sb.AppendFormat("m_{0} = new MenuClass();", this.ClientID);
            sb.AppendFormat("m_{0}.id = '{1}';", this.ClientID, this.HTMLElementId);
            sb.AppendFormat("m_{0}.isOpen = {1};", this.ClientID,
                Helper.GetBool(this.Target == TargetEnum._BLANK));
            sb.AppendFormat("m_{0}.isContextMenu = {1};", this.ClientID,
                (this.Output == OutputEnum.ContextMenu).ToString().ToLower());
            sb.AppendFormat("m_{0}.isCustomer = {1};", this.ClientID,
                (this.Output == OutputEnum.Customer).ToString().ToLower());
            sb.AppendFormat("m_{0}.isHorizontal = {1};", this.ClientID,
                (this.Output == OutputEnum.Horizontal).ToString().ToLower());
            sb.AppendFormat("m_{0}.arrowUrl = '{1}';", this.ClientID, this.ArrowUrl);
            sb.AppendFormat("m_{0}.css = {{", this.ClientID);
            sb.AppendFormat("horizontal: {{ borderColor: '{0}', backColor: '{1}', lineColor: '{2}' }},",
                ColorTranslator.ToHtml(this.Horizontal.BorderColor),
                ColorTranslator.ToHtml(this.Horizontal.BackgroundColor),
                ColorTranslator.ToHtml(this.Horizontal.LineColor));
            sb.AppendFormat("container: {{ borderColor: '{0}', backColor: '{1}', width: '{2}' }},",
                ColorTranslator.ToHtml(this.Container.BorderColor),
                ColorTranslator.ToHtml(this.Container.BackgroundColor),
                this.Container.BorderWidth.Value);
            sb.AppendFormat("icon: {{ borderRightColor: '{0}', backColor: '{1}' }},",
                ColorTranslator.ToHtml(this.Icon.BorderRightColor),
                ColorTranslator.ToHtml(this.Icon.BackgroundColor));
            sb.AppendFormat("text: {{ color: '{0}', family: '{1}', size: '{2}' }},",
                ColorTranslator.ToHtml(this.TextFont.Color),
                this.TextFont.Family,
                this.TextFont.Size.Unit.Value);
            sb.AppendFormat("line: {{ backColor: '{0}' }},",
                ColorTranslator.ToHtml(this.Line.BackgroundColor));
            sb.AppendFormat("over: {{ backColor: '{0}',color: '{1}' }}",
                ColorTranslator.ToHtml(this.Over.BackgroundColor),
                ColorTranslator.ToHtml(this.Over.FontColor));
            sb.AppendFormat("}};");
            sb.AppendFormat("m_{0}.Apply();", this.ClientID);
            sb.Append("})();");
            return sb.ToString();
        }
        /// <summary>
        /// 重写 render
        /// </summary>
        /// <param name="writer">HtmlTextWriter</param>
        protected override void Render(HtmlTextWriter writer) {
            if (this.Items.Count > 0 & string.IsNullOrEmpty(this.HTMLElementId)) {
                this.HTMLElementId = string.Format("divMenu_{0}", this.ClientID);
                writer.AddAttribute(HtmlTextWriterAttribute.Id, this.HTMLElementId);
                writer.RenderBeginTag(HtmlTextWriterTag.Div);
                writer.RenderEndTag();
            }
            this.RenderBeginTag(writer);
            this.RenderContents(writer);
            this.RenderEndTag(writer);
            if (this.DesignMode) { writer.Write(this.ClientID + this.Items.Count.ToString()); }
        }
        /// <summary>
        /// RenderBeginTag
        /// </summary>
        /// <param name="writer">HtmlTextWriter</param>
        public virtual void RenderBeginTag(HtmlTextWriter writer) {
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "text/javascript");
            writer.RenderBeginTag(HtmlTextWriterTag.Script);
        }
        /// <summary>
        /// RenderContents
        /// </summary>
        /// <param name="writer">HtmlTextWriter</param>
        protected internal virtual void RenderContents(HtmlTextWriter writer) {
            base.Render(writer);
            if (this.Items.Count > 0) {
                writer.Write(this.Register());
                writer.Write("(function() {");
                writer.Write(Helper.ConstructMenuItems(new StringBuilder(), 0,
                    this.Items, "m_" + this.ClientID, this.Target));
                writer.Write("})();");
            }
        }
        /// <summary>
        /// RenderEndTag
        /// </summary>
        /// <param name="writer">HtmlTextWriter</param>
        public virtual void RenderEndTag(HtmlTextWriter writer) {
            writer.RenderEndTag();
        }
    }
}
